package com.ruijie.acl.task.loader;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Document;
import org.springframework.util.Assert;

import com.ruijie.acl.task.TaskAclDomain;
import com.ruijie.acl.task.TaskAclUtil;
import com.ruijie.acl.task.model.AccessGroupInfo;
import com.ruijie.acl.task.model.AclDeviceInfo;
import com.ruijie.acl.task.model.TimeRangeInfo;
import com.ruijie.batch.core.factory.SpringConfigAware;
import com.ruijie.batch.plan.PlanParameters;
import com.ruijie.batch.task.ItemProcessResult;
import com.ruijie.emp.batch.task.AbstractDeviceTasklet;
import com.ruijie.emp.device.Device;
import com.ruijie.emp.system.service.TelnetTemplateService;
import com.ruijie.emp.task.EMPTaskDomain;
import com.ruijie.emp.task.util.TaskUtil;
import com.ruijie.foundation.adapter.Adapter;
import com.ruijie.foundation.adapter.parameter.ParameterExecutor;
import com.ruijie.foundation.adapter.parser.ParseInfoUtil;
import com.ruijie.foundation.adapter.parser.Parser;
import com.ruijie.foundation.adapter.utils.Dom4jUtil;
import com.ruijie.foundation.exception.BusinessException;
import com.ruijie.foundation.utils.ExceptionUtils;
import com.ruijie.network.model.TelnetParameter;

/**
 * 
 * <p>
 * Title: TaskLoadAclDeviceInfo
 * </p>
 * <p>
 * Description: 加载ACL Device信息
 * </p>
 * <p>
 * Copyright: Copyright (c) 2008
 * </p>
 * <p>
 * Company: Ruijie Co., Ltd.
 * </p>
 * <p>
 * Create Time: 2009-9-14
 * </p>
 * 
 * @author ASAI
 *         <p>
 *         Update Time:
 *         </p>
 *         <p>
 *         Updater:
 *         </p>
 *         <p>
 *         Update Comments:
 *         </p>
 */
public class TaskLoadAclDeviceInfo extends AbstractDeviceTasklet implements SpringConfigAware {

	private Log logger = LogFactory.getLog(TaskLoadAclDeviceInfo.class);

	TelnetTemplateService service;

	public TelnetTemplateService getService() {
		return service;
	}

	public void setService(TelnetTemplateService service) {
		this.service = service;
	}

	@SuppressWarnings("unchecked")
	public ItemProcessResult processItem(Object item, PlanParameters parameters) {
		ItemProcessResult result = new ItemProcessResult();

		Assert.notNull(item, "item is null");
		Device device = (Device) item;
		// 取得设备的Telnet模板是否成功
		if (device.getTelnetTemplate() == null) {
			if (service != null) {
				logger.warn("device.getTelnetTemplate() is null.");
				device.setTelnetTemplate(service.getDefault());
			}
			if (device.getTelnetTemplate() == null) {
				result.setSuccess(false);
				result.setException(new BusinessException(EMPTaskDomain.EMP_TASK_PARA_TELNETTEMPLOST));
				return result;
			}
		}

		TelnetParameter telnetParameter = TaskUtil.loadTelnetParameter(device, true);

		ParameterExecutor pe = new ParameterExecutor();
		HashMap para = new HashMap();

		String conn = TaskUtil.tranTelnetConnStr(telnetParameter);
		pe.setupInterfaceInfo(TaskUtil.getDeviceSimpleCode(device, "SwitchTelnet"), "");
		pe.setupTargetSystem("", "", "SwitchTelnet", device.getAdminIp(), "" + telnetParameter.getPort(), "", "", conn,
				telnetParameter.getUser(), telnetParameter.getPassword(), "false");
		pe.setupProtocol("", "", "SwitchTelnet", "", "" + telnetParameter.getTimeout(), "", "", "", "", "", "0");

		String prefix = "--More--\\s*end\\s+.*?\\s*?"; // end 然后 提示符号#
		String cmdFormat = "show run\r\n\r\n";
		String cmdPrompt = telnetParameter.isNeedSuPassword() //
		? telnetParameter.getSuPrompt()
				: telnetParameter.getPrompt();

		HashMap cmdShowRun = pe.buildCommandOperate(cmdFormat, prefix + cmdPrompt, prefix + cmdPrompt,
				new HashMap[] { para });

		pe.addCommand(cmdShowRun);

		try {
			Adapter adpater = new Adapter();
			Document doc = pe.getParameter();
			if (logger.isDebugEnabled())
				logger.debug(Dom4jUtil.generateXMLStringBuffer(doc, null).toString());

			String r = (String) adpater.execute(doc);
			doc = Dom4jUtil.createDOM4jDocument(r, false, null);

			String code = doc.getRootElement().selectSingleNode("resultCode").getText();
			device.setConnective(Boolean.valueOf(true));

			String succ = doc.getRootElement().selectSingleNode("isSuccess").getText();
			result.setExecuted(succ.equals("true"));

			String desc = doc.getRootElement().selectSingleNode("workOrderDesc").getText();

			result.setSuccess(Boolean.valueOf(code.equals("true")));
			if (result.getSuccess().booleanValue()) { //
				desc = desc.trim();
				desc = desc.replaceAll(" --More--           ", "");
				desc = desc.replaceAll(" --More--         ", "");
				desc = desc.replaceAll("\\s*--More--\\s*", "\n");

				if (desc.indexOf("!") >= 0) {
					desc = desc.substring(desc.indexOf("!"));
				}
				if (desc.lastIndexOf("\nend") >= 0) {
					desc = desc.substring(0, desc.lastIndexOf("\nend") + 3);
				}
				desc = desc + "\n";

				result.setDesc(desc);

				// 设置到ACL Device信息中
				// AclDeviceInfo aclDeviceInfo =
				// TaskAclUtil.convertAclDeviceInfo(desc);
				AclDeviceInfo aclDeviceInfo = new AclDeviceInfo();
				// 处理返回结果
				Parser parser = new Parser();
				ParseInfoUtil.parseInfo(parser, desc, TaskAclDomain.ACL_PARSER_XML, "acldevice", null);

				// ACL 时间段
				List<TimeRangeInfo> timeRangeInfoList = TaskAclUtil.loadTimeRangeInfo(parser);
				aclDeviceInfo.setTimeRangeInfoList(timeRangeInfoList);
				TaskAclUtil.loadTimeInfo(desc, timeRangeInfoList);
				// ACL 组
				ArrayList<AccessGroupInfo> accessGroupList = new ArrayList<AccessGroupInfo>();
				// 标准ACL规则
				accessGroupList.addAll(TaskAclUtil.loadAccessGroupInfo(parser, "standard"));
				// 扩展ACL规则
				accessGroupList.addAll(TaskAclUtil.loadAccessGroupInfo(parser, "extended"));
				// MAC扩展ACL规则
				accessGroupList.addAll(TaskAclUtil.loadAccessGroupInfo(parser, "mac"));
				// 专家扩展ACL规则
				accessGroupList.addAll(TaskAclUtil.loadAccessGroupInfo(parser, "expert"));
				aclDeviceInfo.setAccessGroupInfoList(accessGroupList);
				TaskAclUtil.loadAceInfo(desc, accessGroupList);
				// ACL 接口
				aclDeviceInfo.setAclInterfaceInfoList(TaskAclUtil.convertAclInterfaceInfo(parser));

				// 设置值
				result.setResultObject(aclDeviceInfo);
			} else {
				// 根据执行结果记录描述信息
				result.setDesc(TaskUtil.buildAdapterReturnMessage(//
						!result.getExecuted(), code.equals("retry"), !result.getSuccess(), desc));
				result.setException(new BusinessException(result.getDesc()));
			}

			return result;
		} catch(Throwable e){
            result.setSuccess(false);
            Throwable cause = ExceptionUtils.resolveActualException(e);
            if(cause instanceof BusinessException){
                result.setDesc(((BusinessException)cause).toParameterizedMessage().toString());
            }
            else{
                result.setException(e);
            }
            logger.error("error while TaskLoadAclDeviceInfo with exception:" + e);
        }
        return result;
	}
}
